var JsonView = (function(view) {

	var REGEX_FORMAT = /\{(.+?)\}/ig;

	var ROOT_HTML = "JsonView" , REMOVE_HTML = "ViewRemove" , CURRENT = "." , ATTR_FOR = "jfor" , ATTR_FROM = "from" , ATTR_SCOPE = "scope"; ATTR_FLUSH = "flush" , NEXTVIEW = "next" , SIZE = "size" , JSONKEY = "jsonkey";

	var _template_views = {};	// TODO 模板分析
	
	var _cascade = {};	// TODO 级联关系分析
	
	var _extend = {};	// TODO 扩展属性分析
	
	var _init_ok = false;	// TODO JsonView初始化
	
	/**
	 * 帮助工具
	 */
	var utils = {

		domain : function(_dom) {
			var scope = _dom.getAttribute(ATTR_SCOPE) || _dom.getAttribute(ATTR_FROM) + ":.";
			!scope && console.error("can not defined scope from" + _dom.tagName);
			return scope;
		},
		
		hashCode : function(str) {
		    var h = 0;
		    var len = str.length;
		    var t = 2147483648;
		    for (var i = 0; i < len; i++) {
		        h = 31 * h + str.charCodeAt(i);
		        if(h > 2147483647) h %= t;
		    }
		    return h;
		},
		
		// TODO 模板分析对象
		retrieval : function(dom) {
			
			var _template = {
				name : dom.tagName,
				attrs : null,
				text : "",
				child : null,
				childlength : null,
				circle : null,
			};
			
			_template.childlength = dom.childElementCount;
			for (var i = 0; i < dom.childElementCount;) {
				if (!_template.child)
					_template.child = new Array();
				_template.child.push(this.retrieval(dom.children[i]));
			}
			_template.attrs = dom.attributes;
			_template.text = utils.trim(dom.textContent);
			_template.circle = dom.getAttribute(ATTR_FOR);
			// TODO 若是根节点,保持其引用,否则删除
			if (dom.root) {
				_template.ref = dom;
			} else {
				dom.remove();
			}
			return _template;
		},
		
		// TODO 元素级联关系分析
		cascade : function(_scope,dom) {
			if(!_cascade[_scope]) {
				_cascade[_scope] = new Array();
				_cascade[_scope].push(_scope);
			}
			var _child = dom.getAttribute(ATTR_FROM);
			if(_child) {
				var _parent = (_child + ":").split(":")[0];
				if(!_cascade[_parent]) {
					_cascade[_parent] = new Array();
					_cascade[_parent].push(_child);
				}
				_cascade[_parent].push(_scope);
			};
			utils.extend(_scope, dom);
		},
		
		// TODO 扩展分析
		extend : function(_scope,dom) {
			_extend[_scope] = {};
			_extend[_scope][JSONKEY] = dom.getAttribute(JSONKEY);
			_extend[_scope][NEXTVIEW] = (dom.nextSibling || dom.parentElement);
			_extend[_scope][SIZE] = 0;
			if(_extend[_scope][JSONKEY]) dom.setAttribute("jfor",".");
		},
		
		getJsonKey : function(_scope) {
			var _scope = _extend[_scope];
			return _scope ? _scope[JSONKEY] : null;
		},
		
		getAndIncrement : function(_dom) {
			var attrs = _dom.attributes;
			var _scope = attrs.scope ? attrs.scope.value : attrs.from.value + ":.";
			return _extend[_scope][SIZE]++;
		},
		
		trim : function(str) {
			return str.replace(/^\s*([\S\s]*?)\s*$/, '$1');
		},

		match : function(str, _data) {
			var result = null;
			while (result = REGEX_FORMAT.exec(str)) {
				var _value = this.getJsonValue(result[1], _data);
				str = str.replace(result[0], _value);
			}
			return str;
		},

		getAttribute : function(_key, attrs) {
			for ( var i in attrs) {
				if (attrs[i].name == _key)
					return attrs[i].value;
			}
		},

		getScope : function(_scope) {
			return _template_views[_scope];
		},

		storeandrunfrom : function(_scope, _element) {
			_template_views[_scope] = _element;
			_element.attrs.from && this._padding(_scope);
		},

		/**提供判断是否过期数据的依据*/
		getValidSessionData : function(k,r,_from){
			var value = this.getSessionData(k,r);
			if(!_from)
				if(value && value.timeout > this.getTime()) {
					return value[k];
				}
			if (!r || "." == r) {
				return value;
			}
			var arr = new Array();
			for(var k in value) {
				arr.push(value[k]);
			}
			return arr;
		},
		
		validData : function(_json) {
			if(_json)
				if(_json && _json.timeout > this.getTime()) {
					return _json;
				}
		},
		
		getTime : function(){
			return new Date().getTime();
		},
		
		setSessionData : function(_result,_timeout) {
			var _scope = _result.scope;
			var realm = _result.realm;
			var _data = _result.json.data;
			var _key = _result.keys;
			var restore = (_result.localstore || {});
			if(_key) {
				var response = new Array().concat(_data);
				response.forEach(function(e,i){
						restore[e[_key]] = e;
						restore[e[_key]]["timeout"] = _timeout;
				});
				_result.response = response.concat(_result.response);
			} else {
				restore[realm] = restore[realm] || {};
				restore[realm]["timeout"] = _timeout;
				restore[realm]["data"] = _data;
				_result.response = _data;
			};
			var jsonview = this.getSessionData(_scope) || {};
			jsonview[realm] = restore[realm];
			localStorage.setItem(this.hashCode(_scope), JSON.stringify(jsonview));
		},

		getSessionData : function(K,R) {
			var V = localStorage.getItem(this.hashCode(K));
			if (!V) V = localStorage.getItem(K);
			return V ? R && "." != R ? JSON.parse(V)[R] : JSON.parse(V) :null;
		},
		
		parseCondition : function(_condition) {
			var regex = /(.+?)=(.+?)/i;
			var r;
			try {
				r = regex.exec(_condition);
				r.length != 3 && console.error("参数错误,例如 id=32");
			} catch (e) {
				alert("参数错误");
			}
			return r;
		},
		
		getJsonValue : function(_key, _data) {
			if (!_key || _key==CURRENT || !_data)
				return _data;
			var key = _key.split(".");
			for ( var i in key) {
				try {
					var p = key[i].indexOf("#");
					if (p != -1) _data = this.dconvert(_data[key[i].substring(0,p)]);
					else _data = _data[key[i]];
				} catch (e) {}
			};
			if (_data) {
				if (typeof _data == "object" && !Array.isArray(_data)) {
					return JSON.stringify(_data);
				} else {
					return _data;
				}
			}
			return "";
		},
		
		dconvert : function(dtime) {
			return new Date(parseInt(dtime)).toLocaleString().replace(/:\d{1,2}$/,' ');
		},
		
		/**
		 * @Param _scope JSON域
		 * @Param _key JSON串中的key，可以用.表示连续的key
		 * @param _condition 循环列表条件
		 */
		deleteJson : function(_scope ,_realm, _key , _condition){
			var JsonValue = this.getSessionData(_scope,_realm);
			if (JsonValue) {
				if(_condition){
					var r = this.parseCondition(_condition);
					if (_key==CURRENT) {
						for (var c = 0; c < JsonValue.length; c++) {
							if(JsonValue[c][r[1]] == r[2]) {
								JsonValue.splice(c--,1);
							}
						}
					} else {
						var key = _key.split(".");
						var tmp = {}; // js当中的引用属于地址引用，非拷贝，所以难点在于如何正确对数据做变量引用，以保证节点能够正确保存。
						for (var i=0; i < key.length;) {
							if (i == 0) {
								tmp[i] = JsonValue[key[i++]];
							} else {
								tmp[i] = tmp[i-1][key[i++]];
							}
						};
						var target = tmp[key.length - 1];
						for (var k=0; k < target.length; k++) {
							if(target[k][r[1]] == r[2]) {
								target.splice(k--,1);
							}
						}
					}
				} else {
					if (_key==CURRENT) {
						JsonValue = "";
					} else {
						var key = _key.split(".");
						var tmp = {};
						for (var i=0; i < key.length;) {
							if (i == 0) {
								tmp[i] = JsonValue[key[i++]];
							} else {
								if(i == key.length - 1){
									delete tmp[i-1][key[i++]];
									break;
								}
								tmp[i] = tmp[i-1][key[i++]];
							}
						};
					}
				}
				this.setSessionData(_scope, JsonValue);
			}
		},
		
		getJson : function(_scope , _realm, _key , _condition) {
			var JsonValue = this.getValidSessionData(_scope,_realm,_condition);
			if (_condition) {
				var r = this.parseCondition(_condition);
				if (_key==CURRENT) {
					for (var c = 0; c < JsonValue.length; c++) {
						if(JsonValue[c][r[1]] == r[2]) {
							return JsonValue[c];
						}
					}
				} else {
					JsonValue = this.getJsonValue(_key, JsonValue);
					for (var c = 0; c < JsonValue.length; c++) {
						if(JsonValue[c][r[1]] == r[2]) {
								return JsonValue[c];
						}
					}
				}
			} else {
				return this.getJsonValue(_key, JsonValue);
			}
		},
		
		fromJson : function(_from) {
			if (_from) {
				var args = (_from + ":").split(":");
				var _data = this.getJson(args[0], args[1], args[2]);
				return _data;
			}
		},
		
		storeAndWrap : function(_result) {
			var _json = _result.json;
			if (_json && _json.success && _json.data) {
				var _timeout = _json.cacheTime ? ( this.getTime() + _json.cacheTime * 1000 ) : 0;
				// TODO 不同的请求（包括参数）对应不同的url hashcode,进而对应不同的scope
				if(_timeout) {
						this.setSessionData(_result,_timeout);	
				}
				// TODO 赋值给response
				_result.response = _json.data
				waitInit(_result);
			}
		},

		//处理返回结果
		inject : function (_result,success) {
			waitInit(_result);
			if(success) {
				success( {
					status : 200,
					data : _result.response,
					success : true,
				} );
			}
		},
		
		// 分析请求参数
		analysis : function(_scope,options) {
			var params = options.data || {};
			var realm = options.realm;
			var result = {
				"request" : new Array(),
				"response" : new Array(),
				"scope" : _scope,
				"pass" : true,
				"keys" : this.getJsonKey(_scope,realm),
			};
			var json = this.getSessionData(_scope,options.realm);
			if(json) {
				if(result.keys) {
					var keys = result.request.concat(params[result.keys]);
					if(keys && keys.length) {
						keys.forEach(function(ele){
							var value = json[ele];
							if(utils.validData(value)) {
								result.response.push(value);
							} else {
								result.request.push(ele);
								result.pass = false;
							}
						});
					};
					if(result.request.length) result.localstore = json;
				} else {
					var value = utils.validData(json) ? json["data"] : result.request.push(_params) - 1;
					if(value) result.response = value; else result.pass = false;
				};
			} else result.pass = false;
			return result;
		},
		
		clear : function(_dom) {
			_dom.innerHTML = "";
			if(!_dom.hasAttribute("noshow")) {
					//_dom.style.display = "block";//清空并显示
			}
		},
		
		/**
		 * @param _element 在此节点之后插入元素
		 * @param operateEle 操作节点
		 * */
		insert : function(operateEle) {
			var scope = operateEle.getAttribute(ATTR_SCOPE);
			var _next = _extend[scope][NEXTVIEW];
			_next.parentElement.insertBefore(operateEle,_next);
		},
		
		hasClass : function(_element,cls) {
			return _element.className.match(new RegExp('(\\s|^)' + cls + '(\\s|$)'));
		},

		addClass : function(_element, cls) {
			if (!this.hasClass(_element, cls)) _element.className += " " + cls;
		},

		removeClass : function(_element, cls) {
			if (hasClass(_element, cls)) {
			    var reg = new RegExp('(\\s|^)' + cls + '(\\s|$)');
			    obj.className = _element.className.replace(reg, ' ');
			}
		},
		
		removeClone : function(){
			_remove = document.getElementsByClassName(REMOVE_HTML);
			var size = _remove.length;
			while(size){
				_remove[--size].remove();
			};
		},
		
		_padding : function(_scope,_data){
			//级联处理
			var cs = _cascade[_scope];
			if(cs){
				cs.forEach(function(cs_scope){
					var f = new ElementFactory(cs_scope,_data);
					f._template && f.json && f.showElement();
				});
			}
		},

		clearJsonData : function(){
			localStorage.clear();
		},
	};
	
	/**
	 * 从模板创建元素
	 */
	function ElementFactory(_scope, _data) {
		if(!_data) this.json = utils.fromJson(_scope) || utils.getValidSessionData(_scope);
		else this.json = _data;
			
		this._template = utils.getScope(_scope);
	};
	
	ElementFactory.prototype = {
		showElement : function() {
			var _template = this._template;
			var currentIndex = _template.ref;
			var flush = currentIndex.hasAttribute(ATTR_FLUSH);
			var length = utils.getAndIncrement(currentIndex);
			// TODO 根节点循环
			if(_template&&_template.circle) {
				var _key = utils.getAttribute(ATTR_FOR, _template.attrs);
				var _value = utils.getJsonValue(_key, this.json);
				if(flush) utils.removeClone();
				for ( var i in _value) {
					var _clone_root = length++ ? currentIndex.cloneNode() : currentIndex;
					utils.addClass(_clone_root,REMOVE_HTML);
					_clone_root = recursive(_template,_value[i],_clone_root);
					// TODO 将克隆并创建生成的节点放到当前节点的下一个兄弟节点
					utils.insert(_clone_root);
				};
			}else{
				recursive(_template,this.json,currentIndex);
			}
			
			/**
			 * 递归创建元素
			 * @param _elements 元素模板
			 * @param _data 元数据
			 * @param  _root 当前节点所在的根节点
			 */
			function recursive(_elements,_data,_root){
				if(!_elements) return;
				// TODO 递归时的父级元素，非根元素
				var _parent = null;
				// TODO 是根节点,清空根节点空格内容
				if(_elements.ref){
					utils.clear(_root);
					_root.textContent = utils.match(_elements.text, _data);
					_parent = _root;
				} else {
					_parent = createElement(_elements, _data);
				}
				// TODO 如果当前节点存在子节点
				if (_elements.childlength) {
					for (var i = 0, len = _elements.childlength; i < len; i++) {
						var child_model = _elements.child[i];
						// TODO for循环元素
						if (child_model.circle) {
							var _key = utils.getAttribute(ATTR_FOR, child_model.attrs);
							var _value = utils.getJsonValue(_key, _data);
							if (_value) {
								for ( var m in _value) {
									var ele_circle = recursive(child_model, _value[m], _parent);
									if(!_elements.ref) _root.appendChild(ele_circle);
								};
							} else {
								var ele_circle = recursive(child_model, "", _parent);
								if(!_elements.ref) _root.appendChild(ele_circle);
							}
						}else{
								recursive(child_model, _data,_parent);
								if(!_elements.ref) _root.appendChild(_parent);
						}
					}
				}else{
					if(!_elements.ref)
						_root.appendChild(_parent);
				}
				return _root;
			}
			// TODO 将模板与数据整合
			function createElement(tmp,json) {
				var tagName = utils.match(tmp.name, json);
				var textContent = utils.match(tmp.text, json);
				var element = document.createElement(tagName);
				element.textContent = textContent;
				var attrs = tmp.attrs;	// TODO 原属性模板，不能修改
				for (var i = 0, len = attrs.length; i < len; i++) {
					if(attrs[i].name != ATTR_FOR && attrs[i].name != ATTR_FROM && attrs[i].name != ATTR_SCOPE) {
						var attr = utils.match(attrs[i].name, json);
						var value = utils.match(attrs[i].value, json);
						element.setAttribute(attr,value);
					}
				}
				return element;
			}
		},
		setJson : function(_data) {
			this.json = _data;
		},
	};
	
	/**
	 ajax请求
	 */
	function AjaxRequest() {
		this.POST = "POST";
		this.GET = "GET";
		this.JSON = 'JSON';
	};

	AjaxRequest.prototype = {
		// TODO 发送请求
		send : function(options) {
			options = options || {};
			options.type = (options.type || this.POST).toUpperCase();
			var params = options.type == this.JSON ? options.data : formatParams(options.data);
			// TODO 执行前置函数
			options.beforeSend && options.beforeSend();
			// TODO 从缓存中获取数据
			var scope = options.scope || "";
			var _result = analysis(scope,options);
			if(_result.pass){
				utils.inject(_result,options.success);
				return;
			};
			// TODO 重新定义params
			if(_result.response.length && _result.keys) {
				options.data[_result.keys] = _result.request;
				params = formatParams(options.data);
			};
			if (window.XMLHttpRequest) {
				var xhr = new XMLHttpRequest();
			} else {
				var xhr = new ActiveXObject('Microsoft.XMLHTTP');
			}
			xhr.onreadystatechange = function() {
				if ( xhr.readyState == 4 ) {
					var status = xhr.status;
					if ( status >= 200 && status < 300 ) {
						var json = JSON.parse(xhr.responseText);
						_result.json = json;
						_result.realm = options.realm
						utils.storeAndWrap(_result);
						options.success && options.success(json);
					} else {
						options.error && options.error(xhr, json);
					}
				}
			};
			// TODO 连接 和 发送 - 第二步
			if (options.type == this.GET) {
				xhr.open(this.GET, getMethod(options), true);
				xhr.send(null);
			} else if (options.type == this.POST || options.type == this.JSON) {
				xhr.open(this.POST, options.url, true);
				if (options.type == this.POST) {
					xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
				} else if (options.type == this.JSON) {
					xhr.setRequestHeader("Content-Type","application/json;chartset=uft-8");
				}
				xhr.setRequestHeader("Access-Control-Allow-Origin", "*");
				xhr.send(params);
			}
			// TODO 缓存中获取数据的key
			function analysis(scope,options) {
				options.realm = utils.hashCode(getMethod(options));
				return utils.analysis(scope,options);
			};
			// TODO 获得get请求
			function getMethod(options){
				options = options || {};
				return options.url + "?" + formatParams(options.data);
			};
			// TODO 参数格式化
			function formatParams(data) {
				var arr = [];
				for ( var name in data) {
					arr.push(encodeURIComponent(name) + "="
							+ encodeURIComponent(data[name]));
				}
				return arr.join("&");
			};
		},
	}

	/**
	 * @param url
	 *            发送请求的地址
	 * @param _type
	 *            post或get
	 * @param param
	 *            发送到服务器的数据，数组存储
	 * @param callfun
	 *            成功回调函数
	 */
	view.ajax = function(options) {
		options = options || {};
		var ajax = new AjaxRequest();
		ajax.send({
			type : options._type,
			url : options._url,
			data : options._data,
			beforeSend : options._beforeSend,
			success : options._success,
			error : options._error,
			scope : options._scope,
		});
	};

	// TODO 检测浏览器是否支持html5
	view.checkBrower = function() {
		if (!window.localStorage) {
			alert("请升级浏览器！");
			return;
		}
	};
	// TODO 等待JsonView初始化
	function waitInit(_result) {
		if(_init_ok){
			utils._padding(_result.scope,_result.response);
		} else {
			setTimeout(function(){waitInit(_result)},10);	//循环
		}
	};
	//	TODO 清空
	view.clear = function(){utils.clearJsonData();}
	//	TODO 删除某个节点
	view.deleteJson = function(scope,jsonKey,condition) {
		utils.deleteJson(scope, jsonKey,condition);
	};
	//	TODO 获取某个节点
	view.getJson = function(scope,jsonKey,condition) {
		return utils.getJson(scope, jsonKey,condition);
	};
	// TODO 初始化
	view.prepare = function() {
		_views = document.getElementsByClassName(ROOT_HTML);
		var size = _views.length;

		while (size) {
			var root = _views[--size];
			var scope = utils.domain(root);
			utils.cascade(scope,root);	//	TODO 级联关系处理
			root.root = true;		//	TODO 标记为根节点
			utils.storeandrunfrom(scope, utils.retrieval(root));	// TODO 自动渲染打上from标签的域
		};
		_init_ok = true;
		return view;
	};
	
	// 自定义函数
	view.init = function() {
		this.checkBrower();
		try {
			if(channel) channel();
		} catch (e) {
			console.info("function channel is not defined");
		}
		this.prepare();
	};
	// 自定义渲染，直接对接数据跟模板, 参数：json data, 页面自定义 scope 
	view.customer_padding = function(data, scope, fun) {
		setTimeout(function(){
			if(_init_ok){
				var f = new ElementFactory(scope,data);
				f._template && f.json && f.showElement();
				if(fun) fun();
			} else {
				JsonView.customer_padding(data, scope, fun);
			}
		},50);
	};
	
	return view;
})(JsonView || {});

window.onload = function(){ JsonView.init();}